/**********************************************************************************************************************
 *
 * Project:    mGameEngine
 * File:       actor.h
 * Author:     twoja stara
 * Created on: 2009-09-24
 *
 **********************************************************************************************************************/

#ifndef ACTOR_H_
#define ACTOR_H_

#include "joint.h"
#include "../common.h"
#include <NxPhysics.h>

namespace mGameEngine
{
namespace Physics
{

/**
 * Physics actor interface.
 * Actors represent single physical object.
 * Different actors have different properties.
 * Two actors can be joined using joints.
 */
class Actor
{
protected:
    /**
     * Joints.
     */
    List<Joint *> _joints;

    /**
     * Actor created.
     */
    mutable bool _created;
    uint8 __padding[3];

    /**
     * Object connected with actor.
     */
    mutable void *_object;

public:
    /**
     * Create PhysX actor for joint.
     * @param joint joint.
     * @return PhysX actor for joint.
     */
    virtual NxActor *_createJointActor(Joint *joint) const = 0;

public:
    /**
     * Create actor.
     */
    Actor();

    /**
     * Destroy actor.
     */
    virtual ~Actor();

    /**
     * Get actors joints.
     * @return actors joints.
     */
    const List<Joint *> &getJoints()
    {
        return _joints;
    }

    /**
     * Add new joint to actor.
     * @param joint joint to add.
     * @param actor actor to join or NULL if second actor is already set.
     */
    virtual void addJoint(Joint *joint, Actor *actor);

    /**
     * Remove joint from actor.
     * Joint will be removed from both joined actors.
     * @param joint joint to remove.
     */
    virtual void removeJoint(Joint *joint);

    /**
     * Put force/momentum to actor.
     * @param force force vector.
     * @param radius radius at which force is put.
     */
    virtual void putForce(const Vector3 &force, const Vector3 &radius = Vector3()) = 0;

    /**
     * Put force/momentum impulse to actor.
     * @param impulse force vector.
     * @param radius radius at which force is put.
     */
    virtual void putImpulse(const Vector3 &impulse, const Vector3 &radius = Vector3()) = 0;

    /**
     * Put acceleration to actor.
     * @param acc acceleration vector.
     * @param radius radius at which acceleration is put.
     */
    virtual void putAcceleration(const Vector3 &acc, const Vector3 &radius = Vector3()) = 0;

    /**
     * Check if actor is already created.
     * @return true if actor is created, false otherwise.
     */
    bool isCreated() const
    {
        return _created;
    }

    /**
     * Create actor on PhysX scene.
     * @param scene PhysX scene.
     */
    virtual void create(NxScene *scene) const = 0;

    /**
     * Get object connected with actor.
     * @return object connected with actor.
     */
    virtual void *getConnectedObject() const;

    /**
     * Set object connected with actor.
     * @return object object to connect with actor.
     */
    virtual void setConnectedObject(void *object);

    /**
     * Get actor transformation.
     * @return actor transformation.
     */
    virtual Matrix4x4 getTransformation() const = 0;

    /**
     * Set actor transformation.
     * @param t transformation.
     */
    virtual void setTransformation(const Matrix4x4 &t) = 0;

    /**
     * Get actor point linear velocity.
     * @param p actor point.
     */
    virtual Vector3 getPointVelocity(const Vector3 &p) = 0;
};

}
}

#endif // ACTOR_H_
